"""
定时任务调度器
"""

import asyncio
from datetime import, timedelta
from typing import Dict, Any, List

from celery.schedules import crontab
from sqlalchemy.ext.asyncio import AsyncSession
from typing import select

from .celery import celery
from database import AsyncSessionLocal
from models.task import Task
from models.execution import Execution
from utils.logger import get_logger

logger = get_logger(__name__)


class TaskScheduler:
    """任务调度器"""

    def __init__(self):
        self.celery_app = celery

    def setup_periodic_tasks(self):
        """设置周期性任务"""
        # 每5分钟执行一次健康检查
        self.celery_app.conf.beat_schedule = {
            "health-check": {
                "task": "app.tasks.sync_tasks.health_check",
                "schedule": 300.0,  # 5分钟
            },
            "cleanup-old-logs": {
                "task": "app.tasks.sync_tasks.cleanup_old_logs",
                "schedule": crontab(hour=2, minute=0),  # 每天凌晨2点
            },
            "check-scheduled-tasks": {
                "task": "app.tasks.scheduler.check_scheduled_tasks",
                "schedule": 60.0,  # 每分钟检查一次
            },
        }

        logger.info("定时任务调度器配置完成")

    async def check_scheduled_tasks(self):
        """检查需要执行的定时任务"""
        logger.info("检查定时任务")

        try:
            async with AsyncSessionLocal() as db:
                # 查询所有激活的定时任务
                stmt = select(Task).where(
                    Task.is_active == True,
                    Task.schedule_config.isnot(None)
                )
                result = await db.execute(stmt)
                tasks = result.scalars().all()

                for task in tasks:
                    if self._should_execute_task(task):
                        await self._schedule_task_execution(task)

        except Exception as e:
            logger.error("检查定时任务失败", error=str(e))

    def _should_execute_task(self, task: Task) -> bool:
        """检查任务是否应该执行"""
        if not task.schedule_config:
            return False

        if not task.schedule_config.get("enabled", False):
            return False

        # TODO: 实现更复杂的时间表达式解析
        # 这里暂时使用简单的检查逻辑
        expression = task.schedule_config.get("expression")
        if not expression:
            return False

        # 检查任务是否已经在运行
        # TODO: 实现任务运行状态检查

        return True

    async def _schedule_task_execution(self, task: Task):
        """调度任务执行"""
        try:
            # 创建执行记录
            async with AsyncSessionLocal() as db:
                execution = Execution(
                    task_id=task.id,
                    status="pending",
                    triggered_by="schedule",
                    branch_mapping=task.branch_mapping,
                )

                db.add(execution)
                await db.commit()
                await db.refresh(execution)

                # 提交同步任务到Celery队列
                from .sync_tasks import execute_git_sync

                execute_git_sync.delay(execution.id)

                logger.info(
                    "定时任务已调度",
                    task_id=task.id,
                    task_name=task.name,
                    execution_id=execution.id
                )

        except Exception as e:
            logger.error(
                "调度定时任务失败",
                task_id=task.id,
                task_name=task.name,
                error=str(e)
            )

    async def get_scheduled_tasks_status(self) -> Dict[str, Any]:
        """获取定时任务状态"""
        try:
            async with AsyncSessionLocal() as db:
                # 查询所有定时任务
                stmt = select(Task).where(
                    Task.is_active == True,
                    Task.schedule_config.isnot(None)
                )
                result = await db.execute(stmt)
                tasks = result.scalars().all()

                scheduled_tasks = []
                for task in tasks:
                    schedule_info = {
                        "task_id": task.id,
                        "task_name": task.name,
                        "schedule_expression": task.schedule_config.get("expression"),
                        "enabled": task.schedule_config.get("enabled", False),
                        "last_execution": None,  # TODO: 获取最后执行时间
                        "next_execution": None,  # TODO: 计算下次执行时间
                    }
                    scheduled_tasks.append(schedule_info)

                return {
                    "total_scheduled_tasks": len(scheduled_tasks),
                    "active_tasks": len([t for t in scheduled_tasks if t["enabled"]]),
                    "tasks": scheduled_tasks
                }

        except Exception as e:
            logger.error("获取定时任务状态失败", error=str(e))
            return {
                "total_scheduled_tasks": 0,
                "active_tasks": 0,
                "tasks": [],
                "error": str(e)
            }


# 全局调度器实例
task_scheduler = TaskScheduler()


# Celery任务：检查定时任务
@celery.task
def check_scheduled_tasks():
    """检查定时任务（Celery任务）"""
    try:
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        try:
            loop.run_until_complete(task_scheduler.check_scheduled_tasks())
            return {"status": "success", "message": "定时任务检查完成"}
        finally:
            loop.close()
    except Exception as e:
        logger.error("定时任务检查失败", error=str(e))
        return {"status": "failure", "error": str(e)}


# Celery任务：获取定时任务状态
@celery.task
def get_scheduled_tasks_status():
    """获取定时任务状态（Celery任务）"""
    try:
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        try:
            status = loop.run_until_complete(task_scheduler.get_scheduled_tasks_status())
            return status
        finally:
            loop.close()
    except Exception as e:
        logger.error("获取定时任务状态失败", error=str(e))
        return {
            "total_scheduled_tasks": 0,
            "active_tasks": 0,
            "tasks": [],
            "error": str(e)
        }


def parse_cron_expression(expression: str) -> Dict[str, Any]:
    """解析Cron表达式"""
    # TODO: 实现完整的Cron表达式解析
    # 这里提供基本的解析逻辑
    parts = expression.split()
    if len(parts) != 5:
        raise ValueError("无效的Cron表达式")

    return {
        "minute": parts[0],
        "hour": parts[1],
        "day": parts[2],
        "month": parts[3],
        "day_of_week": parts[4]
    }


def get_next_execution_time(expression: str, from_time: datetime = None) -> datetime:
    """计算下次执行时间"""
    # TODO: 实现Cron表达式时间计算
    if from_time is None:
        from_time = datetime.utcnow()

    # 简单实现：假设表达式为 "0 2 * * *" (每天凌晨2点)
    if expression == "0 2 * * *":
        next_time = from_time.replace(hour=2, minute=0, second=0, microsecond=0)
        if next_time <= from_time:
            next_time += timedelta(days=1)
        return next_time

    # 默认返回1小时后
    return from_time + timedelta(hours=1)